/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package beans;

import beans.exceptions.NonexistentEntityException;
import entities.Client;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import entities.Cart;
import entities.Orderr;
import java.util.ArrayList;
import java.util.Collection;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ApplicationScoped;


@ManagedBean(name="clientDao")
@ApplicationScoped
public class ClientDAO {

    public ClientDAO() {
        emf = Persistence.createEntityManagerFactory("BookstorePU");
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public void create(Client client) {
        if (client.getOrders() == null) {
            client.setOrders(new ArrayList<Orderr>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Cart cart = client.getCart();
            if (cart != null) {
                cart = em.getReference(cart.getClass(), cart.getId());
                client.setCart(cart);
            }
            Collection<Orderr> attachedOrders = new ArrayList<Orderr>();
            for (Orderr ordersOrderrToAttach : client.getOrders()) {
                ordersOrderrToAttach = em.getReference(ordersOrderrToAttach.getClass(), ordersOrderrToAttach.getId());
                attachedOrders.add(ordersOrderrToAttach);
            }
            client.setOrders(attachedOrders);
            em.persist(client);
            if (cart != null) {
                Client oldClientIdOfCart = cart.getClientId();
                if (oldClientIdOfCart != null) {
                    oldClientIdOfCart.setCart(null);
                    oldClientIdOfCart = em.merge(oldClientIdOfCart);
                }
                cart.setClientId(client);
                cart = em.merge(cart);
            }
            for (Orderr ordersOrderr : client.getOrders()) {
                Client oldClientOfOrdersOrderr = ordersOrderr.getClient();
                ordersOrderr.setClient(client);
                ordersOrderr = em.merge(ordersOrderr);
                if (oldClientOfOrdersOrderr != null) {
                    oldClientOfOrdersOrderr.getOrders().remove(ordersOrderr);
                    oldClientOfOrdersOrderr = em.merge(oldClientOfOrdersOrderr);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(Client client) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Client persistentClient = em.find(Client.class, client.getId());
            Cart cartOld = persistentClient.getCart();
            Cart cartNew = client.getCart();
            Collection<Orderr> ordersOld = persistentClient.getOrders();
            Collection<Orderr> ordersNew = client.getOrders();
            if (cartNew != null) {
                cartNew = em.getReference(cartNew.getClass(), cartNew.getId());
                client.setCart(cartNew);
            }
            Collection<Orderr> attachedOrdersNew = new ArrayList<Orderr>();
            for (Orderr ordersNewOrderrToAttach : ordersNew) {
                ordersNewOrderrToAttach = em.getReference(ordersNewOrderrToAttach.getClass(), ordersNewOrderrToAttach.getId());
                attachedOrdersNew.add(ordersNewOrderrToAttach);
            }
            ordersNew = attachedOrdersNew;
            client.setOrders(ordersNew);
            client = em.merge(client);
            if (cartOld != null && !cartOld.equals(cartNew)) {
                cartOld.setClientId(null);
                cartOld = em.merge(cartOld);
            }
            if (cartNew != null && !cartNew.equals(cartOld)) {
                Client oldClientIdOfCart = cartNew.getClientId();
                if (oldClientIdOfCart != null) {
                    oldClientIdOfCart.setCart(null);
                    oldClientIdOfCart = em.merge(oldClientIdOfCart);
                }
                cartNew.setClientId(client);
                cartNew = em.merge(cartNew);
            }
            for (Orderr ordersOldOrderr : ordersOld) {
                if (!ordersNew.contains(ordersOldOrderr)) {
                    ordersOldOrderr.setClient(null);
                    ordersOldOrderr = em.merge(ordersOldOrderr);
                }
            }
            for (Orderr ordersNewOrderr : ordersNew) {
                if (!ordersOld.contains(ordersNewOrderr)) {
                    Client oldClientOfOrdersNewOrderr = ordersNewOrderr.getClient();
                    ordersNewOrderr.setClient(client);
                    ordersNewOrderr = em.merge(ordersNewOrderr);
                    if (oldClientOfOrdersNewOrderr != null && !oldClientOfOrdersNewOrderr.equals(client)) {
                        oldClientOfOrdersNewOrderr.getOrders().remove(ordersNewOrderr);
                        oldClientOfOrdersNewOrderr = em.merge(oldClientOfOrdersNewOrderr);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Long id = client.getId();
                if (findClient(id) == null) {
                    throw new NonexistentEntityException("The client with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Long id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Client client;
            try {
                client = em.getReference(Client.class, id);
                client.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The client with id " + id + " no longer exists.", enfe);
            }
            Cart cart = client.getCart();
            if (cart != null) {
                cart.setClientId(null);
                cart = em.merge(cart);
            }
            Collection<Orderr> orders = client.getOrders();
            for (Orderr ordersOrderr : orders) {
                ordersOrderr.setClient(null);
                ordersOrderr = em.merge(ordersOrderr);
            }
            em.remove(client);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Client> getAllClients() {
        return getAllClients(true, -1, -1);
    }

    public List<Client> getAllClients(int maxResults, int firstResult) {
        return getAllClients(false, maxResults, firstResult);
    }

    private List<Client> getAllClients(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Client as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Client findClient(Long id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Client.class, id);
        } finally {
            em.close();
        }
    }

    public int getClientCount() {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select count(o) from Client as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

    public Client findClientByLogin(String login, String password) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createNamedQuery("getClientForLogin");
            q.setParameter("clientLogin", login);
            q.setParameter("clientPassword", password);
            List resultList = q.getResultList();
            if (resultList!=null)
                return (Client) resultList.get(0);
            else
                return null;
        } catch (ArrayIndexOutOfBoundsException e) {
            return null;
        } finally {
            em.close();
        }
    }
}
